/* GB2312 Encoding */
/*-----------------------------------------------------------------------
|                            FILE DESCRIPTION                           |
-----------------------------------------------------------------------*/
/*----------------------------------------------------------------------
  - File name     : Stepper_driver.h
  - Author        : liuzhihua (liuzhihuawy@163.com)
  - Update date   : 2023.04.24
  -	Brief         : Stepper Motor Driver
  - Version       : v1.0
-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------
|                               UPDATE NOTE                             |
-----------------------------------------------------------------------*/
/**
  * Update note:
  * ------------   ---------------   ----------------------------------
  *     Date            Author                       Note
  * ------------   ---------------   ----------------------------------
  *  2023.04.22       liuzhihua                   Create file          
***/

#ifndef _STEPPER_DRIVER_H_
#define _STEPPER_DRIVER_H_
#ifdef  __cplusplus
    extern "C" {
#endif
/*-----------------------------------------------------------------------
|                               INCLUDES                                |
-----------------------------------------------------------------------*/
#include <stdint.h>
#include "dma.h"
#include "tim.h"
#include "gpio.h"
/*-----------------------------------------------------------------------
|                                DEFINES                                |
-----------------------------------------------------------------------*/
#define STEPPER_TIM_CLOCK SystemCoreClock
#define STEPPER_DATAMAP_SIZE (100)
#define StepperAssert(expr) ((expr) ? (void)0U : StepperAssert_failed((uint8_t *)__FILE__, __LINE__))

typedef struct 
{
  struct
  {
    GPIO_TypeDef *gpio;
    uint16_t pinBit;
    TIM_HandleTypeDef *htim;
    uint8_t channel;
  } stepCtrl;

  struct 
  {
    GPIO_TypeDef *gpio;
    uint16_t pinBit;
    uint8_t defaultVoltage;
  } dirCtrl;

  struct
  {
    GPIO_TypeDef *gpio;
    uint16_t pinBit;
    uint8_t defaultVoltage;
  } enCtrl;

  long long stepCnt;
  int planStep;
  int curStep;
  int8_t curDir;
  uint8_t endPulse:1;
  uint16_t stepMap[STEPPER_DATAMAP_SIZE];
} stepperDriver_t;

typedef enum 
{
  STEPPER_DRIVER_OK,
  STEPPER_DRIVER_BUSY,
  STEPPER_DRIVER_ERROR
}StepperDriverState_t;

#define StepperGetCompare(hsd)          __HAL_TIM_GET_COMPARE((hsd)->stepCtrl.htim, (hsd)->stepCtrl.channel)
#define StepperSetCompare(hsd, value)   __HAL_TIM_SET_COMPARE((hsd)->stepCtrl.htim, (hsd)->stepCtrl.channel, value)

#define StepperEnable(hsd)              do{HAL_TIM_PWM_Start((hsd)->stepCtrl.htim, (hsd)->stepCtrl.channel);}while(0)
#define StepperDisable(hsd)             do{HAL_TIM_PWM_Stop((hsd)->stepCtrl.htim, (hsd)->stepCtrl.channel);}while(0)

#define StepperGetPeriod(hsd)           __HAL_TIM_GET_AUTORELOAD((hsd)->stepCtrl.htim)
#define StepperSetPeriod(hsd, _period)  __HAL_TIM_SET_AUTORELOAD((hsd)->stepCtrl.htim, _period)
#define StepperGetPrescaler(hsd)        ((hsd)->stepCtrl.htim->Instance->PSC)
#define StepperSetPrescaler(hsd, _psc)  __HAL_TIM_SET_PRESCALER((hsd)->stepCtrl.htim, _psc)

/*-----------------------------------------------------------------------
|                                  API                                  |
-----------------------------------------------------------------------*/
void StepperDriverInit(stepperDriver_t *hsd);

void StepperDriverAttachPulsePin(stepperDriver_t *hsd,
                                 GPIO_TypeDef *gpio,
                                 uint16_t pinBit,
                                 TIM_HandleTypeDef *htim,
                                 uint8_t channel);
void StepperDriverAttachDirPin(stepperDriver_t *hsd,
                               GPIO_TypeDef *gpio,
                               uint16_t pinBit,
                               uint16_t defaultVoltage);
void StepperDriverAttachEnPin(stepperDriver_t *hsd,
                              GPIO_TypeDef *gpio,
                              uint16_t pinBit,
                              uint16_t defaultVoltage);

void StepperDriverSetEnableStatus(stepperDriver_t *hsd, uint8_t status);
uint32_t StepperDriverGetEnableStatus(stepperDriver_t *hsd);

void StepperDriverSetDir(stepperDriver_t *hsd, int dir);
int StepperDriverGetDir(stepperDriver_t *hsd);

StepperDriverState_t StepperDriverMoveSteps(stepperDriver_t *hsd, long steps);
void StepperDriverStopMove(stepperDriver_t *hsd);
StepperDriverState_t StepperDriverMovePos(stepperDriver_t *hsd, long long position);

void StepperDriverSetFrequnce(stepperDriver_t *hsd, uint32_t freq);
uint32_t StepperDriverGetFrequnce(stepperDriver_t *hsd);

long long StepperDriverGetStep(stepperDriver_t *hsd);
StepperDriverState_t StepperDriverGetState(stepperDriver_t *hsd);

void StepperDriverPulseFinishedCallback(stepperDriver_t *hsd, TIM_HandleTypeDef *htim);

__weak void StepperAssert_failed(uint8_t *file, uint32_t line);
#ifdef __cplusplus
	}
#endif
#endif
